package com.wl.application.services.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wl.application.common.all.Const;
import com.wl.application.common.all.Result;
import com.wl.application.common.all.ResultEnum;
import com.wl.application.common.untils.TokenUtil;
import com.wl.application.common.untils.UuidUtil;
import com.wl.application.common.childException.TokenException;
import com.wl.application.common.childException.UserException;
import com.wl.application.common.childException.UserOrPassWordException;
import com.wl.application.context.LoginLocalThread;
import com.wl.application.entity.LoginUser;
import com.wl.application.entity.User;
import com.wl.application.mapper.UserMapper;
import com.wl.application.services.AllotService;
import com.wl.application.services.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author wl
 * @version 1.0
 * @date 2022/6/27
 * @description:
 */
@Service
public class LoginServiceImpl implements LoginService {
    /**
     * 登录的密钥开头
     */
    private final String loginKey = "login_key:";
    @Autowired
    private AllotService service;


    @Resource
    private UserMapper userMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;



    @Override
    public Result exit() {
        //1.获取本地线程中的用户登录数据
        LoginUser local = LoginLocalThread.getLocal();
        Boolean delete = stringRedisTemplate.delete(local.getTokenId());
        if (delete) {
            return Result.ok("退出成功!");
        }
        throw new UserException(ResultEnum.NO_LOGIN.getCode(),"用户退出错误!");
    }

    @Override
    public LoginUser getUserByToken(Map map) {
        return JSON.parseObject(stringRedisTemplate.opsForValue().get(loginKey+map.get("token")),LoginUser.class);
    }

    @Override
    public Result login(Map<String, String> map) {
        //总任务:登录时查出用户的权限保存在本地线程中
        String username = map.get("username");
        String password = map.get("password");
        if (username == null) {
            throw new UserException(1001, "用户名不能为空!");
        }
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("uname", username);
        User user = userMapper.selectOne(wrapper);

        if (user != null) {
            if (user.getUpassword().equals(password)) {
                if (user.getUstate().equals(Const.NO_ACTIVATE)) {
                    //查询该账户是否被冻结
                    throw new TokenException(ResultEnum.USER_FREEZE.getCode(), ResultEnum.USER_FREEZE.getMsg());
                }
                //创建用户token 登录成功时保存用户登录成功的对象到redis中
                LoginUser u = new LoginUser();
                u.setId(user.getId());
                u.setUsername(user.getUname());
                //将密码置为空
                user.setUpassword("");
                u.setUser(user);
                u.setRoleIds(null);
                //生成随机数的uuid
                String uuid = UuidUtil.getUuid();
                u.setTokenId(loginKey + uuid);
                //获得权限的集合
                u.setPowerUrls(service.getAllPowerByUid(user.getId()));
                //将当前的用户信息存入redis中
                //将LoginUser对象转换为json对象
                String loginJson = JSON.toJSONString(u);
                /**
                 * 超时时间
                 */
                long outTime = 30 * 60 * 1000;
                stringRedisTemplate.opsForValue().set(loginKey + uuid, loginJson, outTime, TimeUnit.MILLISECONDS);
                //将当前的信息保存的map中
                Map<String, Object> tokenMap = new HashMap<>();
                tokenMap.put("id", user.getId());
                tokenMap.put("username", user.getUname());
                tokenMap.put("token", uuid);
                String token = TokenUtil.createToken(tokenMap);
                HashMap<String, String> tokenId = new HashMap<>();
                //将token包装一下返回前端
                tokenId.put("token",token);
                //将用户token返回
                //登录成功要将redis中的该用户信息清除
                stringRedisTemplate.delete(user.getId()+"");
                return Result.ok("登录成功!", tokenId);
            }
        }
        //在redis中获取当前用户的登录记录
        if (stringRedisTemplate.opsForValue().get(user.getId().toString()) == null) {
            stringRedisTemplate.opsForValue().set(user.getId().toString(),"1",1,TimeUnit.DAYS);
        }else{
            String freeze = stringRedisTemplate.opsForValue().get(user.getId().toString());
            if(freeze.equals("3")){
                throw new UserException(ResultEnum.USER_UNSAFE.getCode(),ResultEnum.USER_UNSAFE.getMsg());
            }
            stringRedisTemplate.opsForValue().set(user.getId().toString(),String.valueOf(Integer.valueOf(freeze)+1),1,TimeUnit.DAYS);

        }

        throw new UserOrPassWordException(1002, "用户名或密码错误!");
    }
}
